package com.wugui.datax.admin.tool.generate.query;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.wugui.datax.admin.core.util.LocalCacheUtil;
import com.wugui.datax.admin.entity.JobDatasource;
import com.wugui.datax.admin.tool.SpringContextHolder;
import com.wugui.datax.admin.tool.generate.sql.CommonRdbmsGenerateSql;
import com.wugui.datax.admin.tool.generate.sql.GenerateSqlInterface;
import com.wugui.datax.admin.tool.generate.util.QueryBody;
import com.wugui.datax.admin.util.AESUtil;
import com.wugui.datax.admin.util.JdbcConstants;
import com.wugui.datax.admin.util.RdbmsException;
import com.zaxxer.hikari.HikariDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

public class GenerateQueryToolFactory {

    protected static final Logger logger = LoggerFactory.getLogger(GenerateQueryToolFactory.class);

    public static GenerateQueryToolInterface getByDbType(QueryBody queryBody) {
        //获取dbType
        String datasource = queryBody.getDatasource().getDatasource();

        switch (datasource) {
            case JdbcConstants.MYSQL:
            case JdbcConstants.ORACLE:
            case JdbcConstants.POSTGRESQL:
            case JdbcConstants.SQL_SERVER:
            case JdbcConstants.HIVE:
            case JdbcConstants.CLICKHOUSE:
            case JdbcConstants.KINGBASE:
            case JdbcConstants.HBASE20XSQL:
                return getGenerateBaseQueryTool(queryBody);
            case JdbcConstants.HBASE:
                //TODO
                return null;
            case JdbcConstants.MONGODB:
                //TODO
                return null;
        }
        throw new UnsupportedOperationException("找不到该类型: ".concat(datasource));
    }

    private static GenerateQueryToolInterface getGenerateBaseQueryTool(QueryBody queryBody) {
        JobDatasource datasource = queryBody.getDatasource();
        try {
            // 初始化datasource,并进行切换
            cutover(datasource);
            // 获取 DatabaseMetaData
            GenerateSqlInterface ds = new CommonRdbmsGenerateSql(queryBody);
            return new GenerateBaseQueryTool(ds);
        } catch (Exception e) {
            throw RdbmsException.asConnException(datasource.getDatasource(), e, datasource.getJdbcUsername(), datasource.getDatasourceName());
        }
    }

    /**
     * 切换对应数据源
     *
     * @param jobDatasource
     */
    public static void cutover(JobDatasource jobDatasource) throws SQLException {

        DataSource dataSource = null;
        //初始化字段类型信息
        if (LocalCacheUtil.get(jobDatasource.getDatasourceName()) == null) {
            dataSource = getDataSource(jobDatasource);
        } else {
            dataSource = (DataSource) LocalCacheUtil.get(jobDatasource.getDatasourceName());
            Connection connection = dataSource.getConnection();
            if (!connection.isValid(500)) {
                LocalCacheUtil.remove(jobDatasource.getDatasourceName());
                dataSource = getDataSource(jobDatasource);
            }
        }
        LocalCacheUtil.set(jobDatasource.getDatasourceName(), dataSource, 4 * 60 * 60 * 1000);
        DynamicDataSourceContextHolder.push(jobDatasource.getDatasourceName());
    }

    /**
     * 新增数据库
     *
     * @param jobDatasource
     * @return
     */
    private static DataSource getDataSource(JobDatasource jobDatasource) {
        String userName = AESUtil.decrypt(jobDatasource.getJdbcUsername());

        //这里默认使用 hikari 数据源
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setUsername(userName);
        dataSource.setPassword(AESUtil.decrypt(jobDatasource.getJdbcPassword()));
        dataSource.setJdbcUrl(jobDatasource.getJdbcUrl());
        dataSource.setDriverClassName(jobDatasource.getJdbcDriverClass());
        dataSource.setMaximumPoolSize(30);
        dataSource.setMinimumIdle(6);
        dataSource.setConnectionTimeout(30000);

        //动态新增数据源
        DynamicRoutingDataSource ds = SpringContextHolder.getContext().getBean(DynamicRoutingDataSource.class);
        ds.addDataSource(jobDatasource.getDatasourceName(), dataSource);

        return dataSource;
    }
}
